package com.clusterswisdom.horn.api.db;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import com.alibaba.fastjson.JSONObject;
import com.clusterswisdom.horn.api.ioc.api.HornConfig;
import com.clusterswisdom.horn.api.ioc.struct.StructConfig;
import com.clusterswisdom.horn.api.ioc.struct.StructDest;
import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;
import com.jolbox.bonecp.BoneCPDataSource;

public class DbUtil {

	private ThreadLocal<Connection> connection = new ThreadLocal<Connection>();

	private BoneCP connectionPool;

	private SaveLog log;

	private DefaultStructMeger defaultMeger = new DefaultStructMeger();

	private BoneCPDataSource dataSource;

	public static DbUtil util = new DbUtil();

	public static DbUtil getUtil() {
		return util;
	}

	public void init() throws Exception {
		initBonecp();
		log = new SaveLog();
	}

	public BoneCPDataSource getDateSource() {
		if (null == dataSource) {
			return new BoneCPDataSource(connectionPool.getConfig());
		} else {
			return dataSource;
		}

	}

	public Long saveLog(String channel, String ip, String url, String param) {
		try {
			Long id = log.insertLog(getConnection(), channel, ip, url, param);
			commit();
			return id;

		} catch (Exception e) {
			e.printStackTrace();
			rollback();
			return null;

		}
	}
	
	public void logResult(Long id, String type, String response) {
		try {
			log.updateLog(getConnection(), id, type, response);
			commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			rollback();
			
		} 
	}

	public void megerStruct(StructConfig config, JSONObject data) throws SQLException {
		StructDest destConfig = config.getDest();
		StructMeger meger = destConfig.getMeger();
		if (meger == null) {
			meger = defaultMeger;
		}

		meger.megerStruct(getConnection(), config, data);
	}

	private void initBonecp() throws Exception {
		InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(getConfigName());
		Properties properties = new Properties();
		properties.load(is);

		Class.forName(properties.getProperty("driverClass"));
		BoneCPConfig config = new BoneCPConfig(properties);

		connectionPool = new BoneCP(config);
	}

	public Connection getConnection() throws SQLException {
		Connection con = connection.get();
		if (con != null) {
			return con;
			
		} else {
			con = connectionPool.getConnection();
			con.setAutoCommit(false);
			connection.set(con);
			
		}

		return con;
	}

	public void commit() throws SQLException {
		if (connection.get() != null) {
			connection.get().commit();
		}
	}

	public void rollback() {
		try {
			if (connection.get() != null) {
				connection.get().rollback();
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
			
		}
	}

	public void close() {
		try {
			if (connection.get() != null) {
				connection.get().close();
				connection.remove();
			}
			
		} catch (SQLException e) {
			e.printStackTrace();

		}
	}
	
	private String getConfigName() {
		if (HornConfig.getConfig().isRuntime()) {
			return "bonecp.properties";
			
		} else {
			return "bonecp_" + HornConfig.getConfig().getScope() + ".properties";
			
		}
	}
}